package edu.hawaii.senin.iclouds.plotting;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * This class parses standard Iclouds output into IDL - input formatted file.
 *
 * @author Pavel Senin.
 *
 * egrep -e '^[ ]+[A-Z0-9]+[ ]+[0-9]+' CO_feb2006_b.dat | awk '{print $1}' | sed "s/\(.*\)/\<specie\>\1<\/specie\>/" >
 * jacqueline_species.xml
 *
 */
public class Iclouds2idl {

  private static final DecimalFormat decFormat = new DecimalFormat("#####0");

  private static final DecimalFormat decFormatDot = new DecimalFormat("###0.0000");

  private static final DecimalFormat decFormatE = new DecimalFormat("0.0E00");

  /**
   * @param args
   */
  public static void main(String[] args) {

    String SpeciesFileName = "config/jacqueline_output/jacqueline_species_output.xml";
    String TaskAssignment = "config/jacqueline_output/jacqueline_output_assignment.xml";

    try {
      // read species names in
      List<String> species = getSpeciesOfInterest(SpeciesFileName);

      // parsing assignments
      SAXBuilder builder = new SAXBuilder();
      BufferedReader reader = new BufferedReader(new FileReader(new File(TaskAssignment)));
      Document config = builder.build(reader);
      Element root = config.getRootElement();
      Iterator itr = root.getChildren().iterator();
      while (itr.hasNext()) {

        // extract output file name
        Element e = (Element) itr.next();
        String outName = e.getAttributeValue("output");
        // initializing output
        BufferedWriter out = new BufferedWriter(new FileWriter(new File(outName)));
        out.write("        Species        SurfCon       FracAbun         Buried        "
            + "CoReact          React\n");

        // parse all given data files
        Iterator dataItr = e.getChildren().iterator();
        while (dataItr.hasNext()) {

          Element dataEl = (Element) dataItr.next();

          // extract data file name
          String dataName = dataEl.getAttributeValue("data");

          // parse the log
          GeneralLogParser logParser = new GeneralLogParser();
          logParser.parse(dataName);
          GeneralPopulationStorage surfacePopulation = new GeneralPopulationStorage(logParser
              .getActivePopulation());
          GeneralPopulationStorage buriedPopulation = new GeneralPopulationStorage(logParser
              .getBuriedPopulation());
          GeneralPopulationStorage totalPopulation = new GeneralPopulationStorage(logParser
              .getTotalPopulation());
          TreeMap<String, Long> coreactMap = logParser.getCoreactMap();
          TreeMap<String, Long> reactMap = logParser.getReactMap();

          // do the output
          out.write("Den=" + decFormatE.format(logParser.getDensity()));
          out.write(":N=" + decFormatE.format(logParser.getAccretionN()));
          out.write(":D/H=" + decFormatDot.format(logParser.getDHRatio()));
          out.write(":" + logParser.getAuxLine() + "\n");
          out.write(logParser.getAccretedReleased() + "\n");

          StringBuilder logmessage = new StringBuilder(10000);
          Collections.sort(species);

          for (String st : species) {

            // "Species"
            Formatter cf = new Formatter();
            cf.format("%1$15s", st);

            // "SurfCon FracAbun"
            if (surfacePopulation.contains(st)) {
              cf.format("%1$15d%2$15.4f", surfacePopulation.getAmount(st), surfacePopulation
                  .getPercentage(st));
            }
            else {
              cf.format("%1$15d%2$15.4f", 0, 0D);
            }

            // "Buried"
            if (buriedPopulation.contains(st)) {
              cf.format("%1$15d", buriedPopulation.getAmount(st));
            }
            else {
              cf.format("%1$15d", 0);
            }

            // "Coreact"
            if (coreactMap.containsKey(st)) {
              cf.format("%1$15d", coreactMap.get(st));
            }
            else {
              cf.format("%1$15d", 0L);
            }

            // "React"
            if (reactMap.containsKey(st)) {
              cf.format("%1$15d", reactMap.get(st));
            }
            else {
              cf.format("%1$15d", 0L);
            }

            logmessage.append(cf);
            logmessage.append("\n");

          }

          out.write(logmessage.toString());
        }

        // write the stop "signal"
        out.write("\n\n");

        // close output
        out.flush();
        out.close();

      }
    }
    catch (JDOMException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

  }

  /**
   * Parses a file to extract species of interest.
   *
   * @param fileName the file name.
   * @return species of interest as the collection.
   * @throws JDOMException when XML found inappropriate.
   * @throws IOException when IO error encountered.
   */
  private static List<String> getSpeciesOfInterest(String fileName) throws JDOMException,
      IOException {
    SAXBuilder builder = new SAXBuilder();
    BufferedReader reader = new BufferedReader(new FileReader(new File(fileName)));
    Document config = builder.build(reader);
    Element root = config.getRootElement();
    // get list of species of interest
    List<String> speciesOfInterest = new ArrayList<String>();
    List species = root.getChildren();
    Iterator itr = species.iterator();
    while (itr.hasNext()) {
      Element el = (Element) itr.next();
      String specieName = el.getValue();
      speciesOfInterest.add(specieName);
    }
    reader.close();
    return speciesOfInterest;
  }

}
